﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Media;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;

namespace TuanHA_Hunter
{
    public partial class Classname
    {
        #region Attackable

        private static bool Attackable(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid)
                {
                    return false;
                }

                if (SpecialUnit.Contains(target.Entry))
                {
                    return true;
                }

                if (!ValidUnit(target))
                {
                    return false;
                }

                if (Invulnerable(target))
                {
                    return false;
                }

                if (DebuffCCBreakonDamage(target))
                {
                    return false;
                }

                if (!IsEnemy(target))
                {
                    return false;
                }
            }
            return true;
        }

        private static bool Attackable(WoWUnit target, int range)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid)
                {
                    return false;
                }

                if (target.IsBoss || SpecialUnit.Contains(target.Entry))
                {
                    return true;
                }

                if (!ValidUnit(target))
                {
                    return false;
                }

                if (range <= 5 && !target.IsWithinMeleeRange)
                {
                    return false;
                }

                if (range > 5 && target.Distance > range)
                {
                    return false;
                }

                if (range > 5 && !target.InLineOfSpellSight)
                {
                    return false;
                }

                if (Invulnerable(target))
                {
                    return false;
                }

                if (DebuffCCBreakonDamage(target))
                {
                    return false;
                }

                if (!IsEnemy(target))
                {
                    return false;
                }
            }
            return true;
        }

        private static bool AttackableNoCC(WoWUnit target, int range)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid)
                {
                    return false;
                }

                if (!ValidUnit(target))
                {
                    return false;
                }

                if (target.Distance > range)
                {
                    return false;
                }

                if (!target.InLineOfSpellSight)
                {
                    return false;
                }

                if (Invulnerable(target))
                {
                    return false;
                }

                if (!IsEnemy(target))
                {
                    return false;
                }
            }
            return true;
        }

        private static bool AttackableNoLoS(WoWUnit target, int range)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid)
                {
                    return false;
                }

                if (target.IsBoss || SpecialUnit.Contains(target.Entry))
                {
                    return true;
                }

                if (!ValidUnit(target))
                {
                    return false;
                }

                if (range <= 5 && !target.IsWithinMeleeRange)
                {
                    return false;
                }

                if (range > 5 && target.Distance > range)
                {
                    return false;
                }

                if (Invulnerable(target))
                {
                    return false;
                }

                if (DebuffCCBreakonDamage(target))
                {
                    return false;
                }

                if (!IsEnemy(target))
                {
                    return false;
                }
            }
            return true;
        }

        //prevent double ValidUnit Check
        //private static bool AttackableValid(WoWUnit target)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (target.Distance < 40 && !Invulnerable(target) &&
        //            !DebuffCCBreakonDamage(target) && IsEnemy(target) &&
        //            target.InLineOfSpellSight)
        //        {
        //            return true;
        //        }
        //    }
        //    return false;
        //}

        #endregion

        #region  BattleStandard

        private static Composite UseBattleStandard()
        {
            return
                new Decorator(
                    ret =>
                    THSettings.Instance.HealthStone &&
                    Me.Combat &&
                    Me.HealthPercent < THSettings.Instance.HealthStoneHP &&
                    Me.CurrentTarget != null &&
                    Me.CurrentTarget.CurrentHealth > Me.HealthPercent &&
                    Me.CurrentMap.IsBattleground,
                    new Action(delegate
                        {
                            if (Me.IsAlliance)
                            {
                                WoWItem bs = Me.BagItems.FirstOrDefault(o => o.Entry == 18606);
                                //18606 Alliance Battle Standard

                                if (!Me.HasAura("Alliance Battle Standard") && bs != null &&
                                    bs.CooldownTimeLeft.TotalMilliseconds <= _myLatency)
                                {
                                    bs.Use();
                                    //Lua.DoString("RunMacroText(\"/5 Used Healthstone\")");
                                    //Lua.DoString("RunMacroText(\"/s Used Battle Standard\")");
                                    Logging.Write("Use Battle Standard at " + Math.Round(Me.HealthPercent, 0) + "%");
                                }
                            }

                            if (Me.IsHorde)
                            {
                                WoWItem bs = Me.BagItems.FirstOrDefault(o => o.Entry == 18607);
                                //18606 Horde Battle Standard

                                if (!Me.HasAura("Horde Battle Standard") && bs != null &&
                                    bs.CooldownTimeLeft.TotalMilliseconds <= _myLatency)
                                {
                                    bs.Use();
                                    //Lua.DoString("RunMacroText(\"/5 Used Healthstone\")");
                                    //Lua.DoString("RunMacroText(\"/s Used Battle Standard\")");
                                    Logging.Write("Use Battle Standard at " + Math.Round(Me.HealthPercent, 0) + "%");
                                }
                            }

                            return RunStatus.Failure;
                        })
                    );
        }

        #endregion

        #region CanUseEquippedItem

        //Thank Apoc
        private static bool CanUseEquippedItem(WoWItem item)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                // Check for engineering tinkers!
                var itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
                if (string.IsNullOrEmpty(itemSpell))
                    return false;
            }

            return item.Usable && item.Cooldown <= 0;
        }

        #endregion

        #region CastSpell

        private static WoWUnit LastCastUnit;
        private static DateTime LastCastTime = DateTime.Now;
        private static string LastCastSpell = "";
        private static string WriteReason;

        private static void CastSpell(string spellName, WoWUnit u, string reason = "")
        {
            if (spellName != "Freezing Trap" &&
                spellName != "Trap Launcher" &&
                SearchFreezingTrapTime + TimeSpan.FromMilliseconds(3000) > DateTime.Now)
            {
                SpellManager.StopCasting();
                Logging.Write("Skip " + spellName + " and Cast Freezing Trap");
                return;
            }
            //Logging.Write("KillShot: " + SpellManager.CanCast("Kill Shot"), u);
            //return;
            //Logging.Write("Tring to cast " + spellName);
            SpellManager.Cast(spellName, u);
            LastCastTime = DateTime.Now;


            //Prevent spamming
            if (LastCastUnit != u || spellName != LastCastSpell ||
                LastCastTime + TimeSpan.FromMilliseconds(0) < DateTime.Now)
            {
                string barTwo = "Focus: " + PlayerFocus;

                WriteReason = "";
                WriteReason = reason;


                Color colorlog;
                if (u == Me)
                {
                    colorlog = Colors.GreenYellow;
                }

                else if (u == Me.CurrentTarget)
                {
                    colorlog = Colors.Yellow;
                }
                else
                {
                    colorlog = Colors.YellowGreen;
                }

                Logging.Write(colorlog, DateTime.Now.ToString("ss:fff") + " HP: " +
                                        Math.Round(Me.HealthPercent) + "% " + barTwo + " " +
                                        SafeName(u) + " " +
                                        Math.Round(u.Distance, 1) + "y " +
                                        Math.Round(u.HealthPercent) + "% hp " + spellName + " (" + WriteReason + ") ");
            }

            LastCastSpell = spellName;
            LastCastUnit = u;

            //Logging.Write("HoldPetAction: " + HoldPetAction.ToString("ss:fff"));

            //TickMilisecond = DateTime.Now;

            //if (!NoGCDSpells.Contains(spellName))
            //{
            //    UpdateGCD();
            //}


            //if (Me.GotAlivePet)
            //{
            //    Logging.Write("Me.GotAlivePet: " + Me.Pet.Name);
            //}
            //if (Me.Minions.Count > 0)
            //{
            //    Logging.Write("Me.Minions.Count " + Me.Minions.Count);
            //}

            //if (u != Me && Me.CurrentTarget!=null && u==Me.CurrentTarget)
            //{
            //    Logging.Write("u.ThreatInfo: " + u.ThreatInfo);
            //    Logging.Write("u.ThreatInfo.RawPercent: " + u.ThreatInfo.RawPercent);
            //    Logging.Write("u.ThreatInfo.TargetGuid: " + u.ThreatInfo.TargetGuid);
            //    Logging.Write("u.ThreatInfo.ThreatStatus: " + u.ThreatInfo.ThreatStatus);
            //    Logging.Write("u.ThreatInfo.ThreatValue: " + u.ThreatInfo.ThreatValue);
            //}
        }

        #endregion

        #region CanCleanse

        //private static bool CanCleanse(WoWAura aura)
        //{
        //    //if (aura == null)
        //    //    return false;

        //    //if (aura.Spell.DispelType == WoWDispelType.Disease || aura.Spell.DispelType == WoWDispelType.Magic ||
        //    //    aura.Spell.DispelType == WoWDispelType.Poison)
        //    if (aura.Spell.DispelType != WoWDispelType.None)
        //    {
        //        //Logging.Write("CanCleanse: " + aura.Name + " - " + aura.SpellId);
        //        return true;
        //    }
        //    return false;
        //}

        #endregion

        #region ConstantFace

        //private static void ConstantFace(WoWUnit unit)
        //{
        //    if (!IsOverrideModeOn && !Me.IsSafelyFacing(unit))
        //    {
        //        WoWMovement.ConstantFace(unit.Guid);
        //    }
        //}

        #endregion

        #region CountDebuff

        //public static double CountDebuff(WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        int numberofDebuff =
        //            u.Debuffs.Values.Count(
        //                debuff =>
        //                (debuff.Spell.DispelType == WoWDispelType.Magic ||
        //                 debuff.Spell.DispelType == WoWDispelType.Poison ||
        //                 debuff.Spell.DispelType == WoWDispelType.Disease));

        //        return numberofDebuff;
        //    }
        //}

        private static double CountDebuffAll(WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                int numberofDebuff =
                    u.Debuffs.Values.Count();

                return numberofDebuff;
            }
        }

        private static double CountDebuffMagic(WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                int numberofDebuff =
                    u.Debuffs.Values.Count(
                        debuff =>
                        (debuff.Spell.DispelType == WoWDispelType.Magic));

                return numberofDebuff;
            }
        }

        //private static double CountDebuffRootandSnareMechanic(WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        return
        //            u.ActiveAuras.Values.Count(
        //                debuff =>
        //                (debuff.Spell.Mechanic == WoWSpellMechanic.Snared ||
        //                 debuff.Spell.Mechanic == WoWSpellMechanic.Rooted));
        //    }
        //}

        #endregion

        #region CountDPSTarget

        private static int CountDPSTarget(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
                {
                    return NearbyUnFriendlyUnits.Count(
                        unit =>
                        unit.IsValid &&
                        unit.IsPlayer &&
                        unit.CurrentTarget != null &&
                        unit.CurrentTarget.IsValid &&
                        unit.CurrentTarget == target &&
                        (TalentSort(unit) >= 2 &&
                         TalentSort(unit) <= 3 &&
                         unit.Location.Distance(target.Location) < 40 ||
                         TalentSort(unit) == 1 &&
                         unit.Location.Distance(target.Location) < 15) &&
                        !DebuffCC(unit));
                }
                return NearbyUnFriendlyUnits.Count(
                    unit =>
                    unit.IsValid &&
                    unit.CurrentTarget != null &&
                    unit.CurrentTarget.IsValid &&
                    unit.CurrentTarget == target &&
                    !DebuffCC(unit));
            }
        }

        #endregion

        #region CountMagicDPSTarget

        //private static int CountMagicDPSTarget(WoWUnit target)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
        //        {
        //            return NearbyUnFriendlyUnits.Count(
        //                unit =>
        //                unit.IsValid &&
        //                unit.IsPlayer &&
        //                unit.CurrentTarget != null &&
        //                unit.CurrentTarget.IsValid &&
        //                unit.CurrentTarget == target &&
        //                TalentSort(unit) == 3 &&
        //                unit.Location.Distance(target.Location) < 40 &&
        //                !DebuffCC(unit));
        //        }
        //        return NearbyUnFriendlyUnits.Count(
        //            unit =>
        //            unit.IsValid &&
        //            unit.CurrentTarget != null &&
        //            unit.CurrentTarget.IsValid &&
        //            unit.CurrentTarget == target &&
        //            unit.PowerType == WoWPowerType.Mana &&
        //            unit.Location.Distance(target.Location) < 40 &&
        //            !DebuffCC(unit));
        //    }
        //}

        #endregion

        #region CountMeleeDPSTarget

        private static int CountMeleeDPSTarget(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
                {
                    return NearbyUnFriendlyUnits.Count(
                        unit =>
                        unit.IsValid &&
                        unit.IsPlayer &&
                        unit.CurrentTarget != null &&
                        unit.CurrentTarget.IsValid &&
                        unit.CurrentTarget == target &&
                        TalentSort(unit) == 1 &&
                        unit.Location.Distance(target.Location) < 15 &&
                        !DebuffCC(unit));
                }
                return NearbyUnFriendlyUnits.Count(
                    unit =>
                    unit.IsValid &&
                    unit.CurrentTarget != null &&
                    unit.CurrentTarget.IsValid &&
                    unit.CurrentTarget == target &&
                    unit.Location.Distance(target.Location) < 15 &&
                    !DebuffCC(unit));
            }
        }

        #endregion

        #region CountPhysicDPSTarget

        //private static int CountPhysicDPSTarget(WoWUnit target)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
        //        {
        //            return NearbyUnFriendlyUnits.Count(
        //                unit =>
        //                unit.IsValid &&
        //                unit.IsPlayer &&
        //                unit.CurrentTarget != null &&
        //                unit.CurrentTarget.IsValid &&
        //                unit.CurrentTarget == target &&
        //                (TalentSort(unit) == 2 &&
        //                 unit.Location.Distance(target.Location) < 40 ||
        //                 TalentSort(unit) == 1 &&
        //                 unit.Location.Distance(target.Location) < 25) &&
        //                !DebuffCC(unit));
        //        }
        //        return NearbyUnFriendlyUnits.Count(
        //            unit =>
        //            unit.IsValid &&
        //            unit.CurrentTarget != null &&
        //            unit.CurrentTarget.IsValid &&
        //            unit.CurrentTarget == target &&
        //            unit.Location.Distance(target.Location) < 15 &&
        //            !DebuffCC(unit));
        //    }
        //}

        #endregion

        #region CountEnemyNear

        private static double CountEnemyNear(WoWUnit unitCenter, float distance)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                return
                    NearbyUnFriendlyUnits.Where(
                        unit =>
                        unit.IsValid &&
                        unitCenter.Location.Distance(unit.Location) <= distance &&
                        (unit.Combat || !Me.IsInInstance && IsDummy(unit)) &&
                        !unit.IsPet &&
                        (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                         !Me.IsInInstance && (unit.IsTargetingMeOrPet || IsDummy(unit)))).Aggregate
                        <WoWUnit, double>(0, (current, unit) => current + 1);
            }
        }

        #endregion

        #region CountEnemyNearTarget

        private static int CountEnemyNearTarget(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                return NearbyUnFriendlyUnits.Count(
                    unit =>
                    unit.IsValid &&
                    unit.CurrentTarget != null &&
                    unit.CurrentTarget.IsValid &&
                    unit.CurrentTarget == target &&
                    !DebuffCC(unit));
            }
        }

        #endregion

        #region CountEnemyNearNoCC

        //private static double CountEnemyNearNoCC(WoWUnit unitCenter, float distance)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return
        //            NearbyUnFriendlyUnits.Where(
        //                unit =>
        //                unit.IsValid &&
        //                unitCenter.Location.Distance(unit.Location) <= distance &&
        //                (unit.Combat || !Me.IsInInstance && IsDummy(unit)) &&
        //                !unit.IsPet &&
        //                !DebuffCC(unit) &&
        //                (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
        //                 !Me.IsInInstance && (unit.IsTargetingMeOrPet || IsDummy(unit)))).Aggregate
        //                <WoWUnit, double>(0, (current, unit) => current + 1);
        //    }
        //}

        #endregion

        #region CountEnemyNearNoCCBreakonDamge

        //private static double CountEnemyNearNoCCBreakonDamge(WoWUnit unitCenter, float distance)
        //{
        //    if (unitCenter == null || unitCenter.IsValid)
        //    {
        //        return 0;
        //    }
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return
        //            NearbyUnFriendlyUnits.Where(
        //                unit =>
        //                unit.IsValid &&
        //                unitCenter.Location.Distance(unit.Location) <= distance &&
        //                DebuffCCBreakonDamage(unit)).Aggregate
        //                <WoWUnit, double>(0, (current, unit) => current + 1);
        //    }
        //}

        #endregion

        #region CountEnemyPestilence

        //private static double CountEnemyDontHaveBloodPlagueorFrostFever(WoWUnit unitCenter, float distance)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return
        //            NearbyUnFriendlyUnits.Where(
        //                unit =>
        //                unit.IsValid &&
        //                unitCenter.Location.Distance(unit.Location) <= distance &&
        //                (unit.Combat || !Me.IsInInstance && IsDummy(unit)) &&
        //                !unit.IsPet &&
        //                (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
        //                 !Me.IsInInstance && (unit.IsTargetingMeOrPet || IsDummy(unit))) &&
        //                !Invulnerable(unit) &&
        //                (!MyAura("Frost Fever", unit) ||
        //                 !MyAura("Blood Plague", unit))).Aggregate
        //                <WoWUnit, double>(0, (current, unit) => current + 1);
        //    }
        //}

        #endregion

        #region CountEnemyFromPoint

        //private static double CountEnemyFromPoint(WoWPoint pointCenter, float radius)
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            pointCenter.Distance(unit.Location) <= radius &&
        //            unit.Combat).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountEneyTargettingUnit

        //private static double CountEneyTargettingUnit(WoWUnit target, float distance)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return
        //            NearbyUnFriendlyUnits.Where(
        //                unit =>
        //                unit.IsValid &&
        //                GetMinDistance(unit) < distance &&
        //                unit.CurrentTarget != null &&
        //                unit.CurrentTarget.IsValid &&
        //                unit.Level <= target.Level + 3 &&
        //                //unit.Combat && 
        //                !unit.IsPet &&
        //                unit.CurrentTarget == target //&&
        //                //DebuffCC(unit) <= MyLatency
        //                ).Aggregate
        //                <WoWUnit, double>(0, (current, unit) => current + 1);
        //    }
        //}

        #endregion

        #region CountEnemyNearNoCCBreakonDamge

        private static double CountEnemyNearNoCCBreakonDamge(WoWUnit unitCenter, float distance)
        {
            if (unitCenter == null || unitCenter.IsValid || !Me.CurrentMap.IsArena && !Me.CurrentMap.IsBattleground)
            {
                return 0;
            }
            return
                NearbyUnFriendlyPlayers.Where(
                    unit =>
                    unit.IsValid &&
                    unitCenter.Location.Distance(unit.Location) <= distance &&
                    DebuffCCBreakonDamage(unit)).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        #endregion

        #region FacingOverride

        private static bool FacingOverride(WoWUnit unit)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (unit == null || !unit.IsValid)
                {
                    return false;
                }

                if (SpecialUnit.Contains(unit.Entry))
                {
                    return true;
                }

                if (Me.IsFacing(unit))
                {
                    return true;
                }

                if (!IsOverrideModeOn &&
                    THSettings.Instance.AutoFace &&
                    (TreeRoot.Current.Name == "Questing" ||
                     TreeRoot.Current.Name == "Grind Bot"))
                {
                    return true;
                }

                return false;
            }
        }

        #endregion

        #region FacingOverrideWide

        private static bool FacingOverrideWide(WoWUnit unit)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (unit == null)
                {
                    return false;
                }

                if (SpecialUnit.Contains(unit.Entry))
                {
                    return true;
                }

                if (Me.IsSafelyFacing(unit, 220))
                {
                    return true;
                }

                if (!IsOverrideModeOn &&
                    THSettings.Instance.AutoFace &&
                    (TreeRoot.Current.Name == "Questing" ||
                     TreeRoot.Current.Name == "Grind Bot"))
                {
                    return true;
                }

                return false;
            }
        }

        #endregion

        #region GatherData

        //private static readonly HashSet<int> _spellIDGather = new HashSet<int>
        //    {
        //        11196,
        //    };

        //public List<string> DebuffandCastCollected = new List<string>();

        //private static string GetCreateClassName(ulong createdbyguid)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        WoWPlayer unitcreateaura = (from unit in ObjectManager.GetObjectsOfType<WoWPlayer>(true, true)
        //                                    where unit.Guid == createdbyguid
        //                                    select unit).FirstOrDefault();

        //        if (unitcreateaura != null && unitcreateaura.IsPlayer)
        //        {
        //            return unitcreateaura.Class.ToString();
        //        }
        //        if (unitcreateaura != null && unitcreateaura.IsPet)
        //        {
        //            return unitcreateaura.Class.ToString() + " (Pet)";
        //        }
        //    }
        //    return "";
        //}

        //private static void GatherData()
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        List<WoWUnit> allUnit = ObjectManager.GetObjectsOfType<WoWUnit>(true, true);

        //        foreach (WoWUnit unit in allUnit)
        //        {
        //            foreach (var aura in unit.Debuffs)
        //            {
        //                if (!_spellIDGather.Contains(aura.Value.SpellId) &&
        //                    GetCreateClassName(aura.Value.CreatorGuid) != "")
        //                {
        //                    _spellIDGather.Add(aura.Value.SpellId);
        //                    //Logging.Write(GetCreateClassName(aura.Value.CreatorGuid) + "|" + "Debuff" + "|" + aura.Value.SpellId + "|" + aura.Value.Name + "|" + aura.Value.Spell.DispelType + "|" + aura.Value.Spell.Mechanic + "|" + aura.Value.Spell.BaseCooldown);
        //                    DebuffandCastCollected.Add(GetCreateClassName(aura.Value.CreatorGuid) + "|" + "Debuff" + "|" +
        //                                               aura.Value.SpellId + "|" + aura.Value.Name + "|" +
        //                                               aura.Value.Spell.DispelType + "|" + aura.Value.Spell.Mechanic +
        //                                               "|" + aura.Value.Spell.BaseCooldown);
        //                }
        //            }

        //            if (unit.IsCasting && !_spellIDGather.Contains(unit.CastingSpellId) &&
        //                GetCreateClassName(unit.Guid) != "")
        //            {
        //                _spellIDGather.Add(unit.CastingSpellId);
        //                //Logging.Write(unit.Class.ToString() + "|" + "Casting" + "|" + unit.CastingSpellId + "|" + unit.CastingSpell.Name + "|" +unit.CastingSpell.DispelType + "|" + unit.CastingSpell.Mechanic + "|" + unit.CastingSpell.BaseCooldown);
        //                DebuffandCastCollected.Add(unit.Class.ToString() + "|" + "Casting" + "|" + unit.CastingSpellId +
        //                                           "|" + unit.CastingSpell.Name + "|" + unit.CastingSpell.DispelType +
        //                                           "|" + unit.CastingSpell.Mechanic + "|" +
        //                                           unit.CastingSpell.BaseCooldown);
        //            }

        //            //foreach (var aura in unit.Buffs)
        //            //{
        //            //    if (!_spellIDGather.Contains(aura.Value.SpellId))
        //            //    {
        //            //        _spellIDGather.Add(aura.Value.SpellId);
        //            //        Logging.Write("Buff," + aura.Value.SpellId + "," + aura.Value.Name + "," + aura.Value.Spell.DispelType + "," + aura.Value.Spell.Mechanic + "," + aura.Value.Spell.BaseCooldown);
        //            //    }
        //            //}
        //        }
        //    }
        //}

        #endregion

        #region GCD

        //private static void UpdateGCDEvent(object sender, LuaEventArgs raw)
        //{
        //    var args = raw.Args;
        //    var player = Convert.ToString(args[0]);

        //    // Not me ... Im out!
        //    if (player != "player")
        //    {
        //        return;
        //    }
        //    var spellID = Convert.ToInt32(args[4]);
        //    var spellName = WoWSpell.FromId(spellID).Name;

        //}

        //public static void UpdateGCD()
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        _gcdReady = DateTime.Now + SpellManager.GlobalCooldownLeft;
        //    }
        //}

        private static bool GCDL()
        {
            if ((DateTime.Now - LastCastTime).TotalMilliseconds < _myLatency &&
                SpellManager.GlobalCooldownLeft.TotalMilliseconds > _myLatency)
            {
                //Logging.Write("GCDL TRUE");
                return true;
            }
            return false;
        }

        private static bool Casting()
        {
            if (Me.IsCasting &&
                Me.CastingSpellId != 77767 &&
                Me.CastingSpellId != 53341)
            {
                return true;
            }

            if (Me.IsChanneling &&
                Me.ChanneledCastingSpellId != 120360)
            {
                return true;
            }

            return false;
        }


        private static bool CastingorGCDL()
        {
            return Casting() || GCDL();
        }

        #endregion

        #region GetAsyncKeyState

        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        #endregion

        #region GetCurrentSpec

        public static string GetCurrentSpec()
        {
            if (Me.Specialization == WoWSpec.HunterBeastMastery)
            {
                return "BeastMastery";
            }
            if (Me.Specialization == WoWSpec.HunterMarksmanship)
            {
                return "Marksmanship";
            }
            else if (Me.Specialization == WoWSpec.HunterSurvival)
            {
                return "Survival";
            }
            Logging.Write("No Specialization detected");
            return "No Specialization detected";
        }

        #endregion

        #region GetSpellCooldown

        /// <summary>
        /// gets the current Cooldown remaining for the spell. indetermValue returned if spell not known
        /// </summary>
        /// <param name="spell">spell to retrieve cooldown for</param>
        /// <param name="indetermValue">value returned if spell not defined</param>
        /// <returns>TimeSpan representing cooldown remaining, indetermValue if spell unknown</returns>
        private TimeSpan GetSpellCooldown(string spell, int indetermValue = int.MaxValue)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                SpellFindResults sfr;
                if (SpellManager.FindSpell(spell, out sfr))
                    return (sfr.Override ?? sfr.Original).CooldownTimeLeft;

                if (indetermValue == int.MaxValue)
                    return TimeSpan.MaxValue;
            }
            return TimeSpan.FromSeconds(indetermValue);
        }

        private static bool IsSpellOnCooldown(string spell)
        {
            SpellFindResults sfr;
            if (SpellManager.FindSpell(spell, out sfr))
                return (sfr.Override ?? sfr.Original).Cooldown;

            return true;
        }

        //private static double GetSpellCooldown(int spell)
        //{
        //    try
        //    {
        //        SpellFindResults results;
        //        if (SpellManager.FindSpell(spell, out results))
        //        {
        //            var conv = results.Override != null ? results.Override.Name : results.Original.Name;
        //            //using (StyxWoW.Memory.AcquireFrame())
        //            {
        //                return Lua.GetReturnVal<int>("return GetSpellCooldown(\"" + conv + "\");", 1);
        //            }
        //        }

        //        return 0;
        //    }
        //    catch
        //    {
        //        return 0;
        //    }
        //}

        //private static double GetSpellCooldown(string spell)
        //{
        //    try
        //    {
        //        SpellFindResults results;
        //        if (SpellManager.FindSpell(spell, out results))
        //        {
        //            var conv = results.Override != null ? results.Override.Name : results.Original.Name;
        //            //using (StyxWoW.Memory.AcquireFrame())
        //            {
        //                return Lua.GetReturnVal<int>("return GetSpellCooldown(\"" + conv + "\");", 1);
        //            }
        //        }

        //        return 0;
        //    }
        //    catch
        //    {
        //        return 0;
        //    }
        //}

        //public static TimeSpan GetSpellCooldown(string spell)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        SpellFindResults results;
        //        if (SpellManager.FindSpell(spell, out results))
        //        {
        //            return results.Override != null
        //                       ? results.Override.CooldownTimeLeft
        //                       : results.Original.CooldownTimeLeft;
        //        }

        //        return TimeSpan.MaxValue;
        //    }
        //}

        #endregion

        #region GetUnitAuras

        //private static double AuraCCDuration;
        //private static double AuraCCDurationMax;
        //public WoWAura AuraCC;

        //private static double AuraCCBreakonDamageDuration;
        //private static double AuraCCBreakonDamageDurationMax;
        //public WoWAura AuraCCBreakonDamage;

        //private static double AuraDisarmDuration;
        //private static double AuraDisarmDurationMax;
        //public WoWAura AuraDisarm;

        //private static double AuraImmuneDuration;
        //private static double AuraImmuneDurationMax;
        //public WoWAura AuraImmune;

        //private static double AuraImmunePhysicDuration;
        //private static double AuraImmunePhysicDurationMax;
        //public WoWAura AuraImmunePhysic;

        //private static double AuraImmuneSpellDuration;
        //private static double AuraImmuneSpellDurationMax;
        //public WoWAura AuraImmuneSpell;

        //private static double AuraRootDuration;
        //private static double AuraRootDurationMax;
        //public WoWAura AuraRoot;

        //private static double AuraSilenceDuration;
        //private static double AuraSilenceDurationMax;
        //public WoWAura AuraSilence;

        //private static double AuraSnareDuration;
        //private static double AuraSnareDurationMax;
        //public WoWAura AuraSnare;

        //public WoWAura AuraCleanseDoNot;
        //public WoWAura AuraHealDoNot;
        //public int NumberofDebuff;

        //private static bool GetUnitAuras(WoWUnit u)
        //{
        //    if (u == null || !u.IsValid || !u.IsAlive)
        //        return false;

        //    AuraCC = null;
        //    AuraCCDuration = 0;
        //    AuraCCDurationMax = 0;

        //    AuraCCBreakonDamage = null;
        //    AuraCCBreakonDamageDuration = 0;
        //    AuraCCBreakonDamageDurationMax = 0;

        //    AuraDisarm = null;
        //    AuraDisarmDuration = 0;
        //    AuraDisarmDurationMax = 0;

        //    AuraImmune = null;
        //    AuraImmuneDuration = 0;
        //    AuraImmuneDurationMax = 0;

        //    AuraImmuneSpell = null;
        //    AuraImmuneSpellDuration = 0;
        //    AuraImmuneSpellDurationMax = 0;

        //    AuraImmunePhysic = null;
        //    AuraImmunePhysicDuration = 0;
        //    AuraImmunePhysicDurationMax = 0;

        //    AuraRoot = null;
        //    AuraRootDuration = 0;
        //    AuraRootDurationMax = 0;

        //    AuraSilence = null;
        //    AuraSilenceDuration = 0;
        //    AuraSilenceDurationMax = 0;

        //    AuraSnare = null;
        //    AuraSnareDuration = 0;
        //    AuraSnareDurationMax = 0;

        //    NumberofDebuff = 0;
        //    AuraCleanseDoNot = null;
        //    AuraHealDoNot = null;

        //    foreach (var aura in u.GetAllAuras())
        //    {
        //        //Count Number of Debuff
        //        if (aura.IsHarmful &&
        //            (aura.Spell.DispelType == WoWDispelType.Disease ||
        //             aura.Spell.DispelType == WoWDispelType.Magic ||
        //             aura.Spell.DispelType == WoWDispelType.Poison))
        //        {
        //            NumberofDebuff = NumberofDebuff + 1;
        //        }

        //        //Find out if AuraCleanseDoNot exits
        //        if (ListCleanseDoNot.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraCleanseDoNot = aura.;
        //        }

        //        //Find out if AuraHealDoNot exits
        //        if (ListHealDoNot.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraHealDoNot = aura.;
        //        }

        //        if (ListCC.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraCCDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraCCDuration > AuraCCDurationMax)
        //            {
        //                AuraCC = aura.;
        //                AuraCCDurationMax = AuraCCDuration;
        //            }
        //        }

        //        if (ListCCBreakonDamage.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraCCBreakonDamageDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraCCBreakonDamageDuration > AuraCCBreakonDamageDurationMax)
        //            {
        //                AuraCCBreakonDamage = aura.;
        //                AuraCCBreakonDamageDurationMax = AuraCCBreakonDamageDuration;
        //            }
        //        }

        //        if (ListDisarm.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraDisarmDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraDisarmDuration > AuraDisarmDurationMax)
        //            {
        //                AuraDisarm = aura.;
        //                AuraDisarmDurationMax = AuraDisarmDuration;
        //            }
        //        }

        //        if (ListImmune.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraImmuneDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraImmuneDuration > AuraImmuneDurationMax)
        //            {
        //                AuraImmune = aura.;
        //                AuraImmuneDurationMax = AuraImmuneDuration;
        //            }
        //        }

        //        if (ListImmuneSpell.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraImmuneSpellDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraImmuneSpellDuration > AuraImmuneSpellDurationMax)
        //            {
        //                AuraImmuneSpell = aura.;
        //                AuraImmuneSpellDurationMax = AuraImmuneSpellDuration;
        //            }
        //        }

        //        if (ListImmunePhysic.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraImmunePhysicDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraImmunePhysicDuration > AuraImmunePhysicDurationMax)
        //            {
        //                AuraImmunePhysic = aura.;
        //                AuraImmunePhysicDurationMax = AuraImmunePhysicDuration;
        //            }
        //        }

        //        if (ListRoot.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraRootDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraRootDuration > AuraRootDurationMax)
        //            {
        //                AuraRoot = aura.;
        //                AuraRootDurationMax = AuraRootDuration;
        //            }
        //        }

        //        if (ListSilence.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraSilenceDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraSilenceDuration > AuraSilenceDurationMax)
        //            {
        //                AuraSilence = aura.;
        //                AuraSilenceDurationMax = AuraSilenceDuration;
        //            }
        //        }

        //        if (ListSnare.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraSnareDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraSnareDuration > AuraSnareDurationMax)
        //            {
        //                AuraSnare = aura.;
        //                AuraSnareDurationMax = AuraSnareDuration;
        //            }
        //        }
        //    }
        //    return true;
        //}

        #endregion

        #region GetAllMyAuras

        //private static DateTime _lastGetAllMyAuras = DateTime.Now;

        //private static void DumpAuras()
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (_lastGetAllMyAuras.AddSeconds(10) < DateTime.Now)
        //        {
        //            int i = 1;
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");
        //            foreach (WoWAura aura in Me.GetAllAuras())
        //            {
        //                Logging.Write(LogLevel.Diagnostic,
        //                              i + ". Me.GetAllAuras Name: " + aura.Name + " - SpellId: " + aura.SpellId);
        //                i = i + 1;
        //            }
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");

        //            i = 1;
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");
        //            foreach (var aura in Me.Auras)
        //            {
        //                Logging.Write(LogLevel.Diagnostic,
        //                              i + ". Me.Auras - Name: " + aura.Value.Name + " - SpellId: " + aura.Value.SpellId);
        //                i = i + 1;
        //            }
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");

        //            i = 1;
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");
        //            foreach (var aura in Me.ActiveAuras)
        //            {
        //                Logging.Write(LogLevel.Diagnostic,
        //                              i + ". Me.ActiveAuras - Name: " + aura.Value.Name + " - SpellId: " +
        //                              aura.Value.SpellId);
        //                i = i + 1;
        //            }
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");

        //            i = 1;
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");
        //            foreach (var aura in Me.PassiveAuras)
        //            {
        //                Logging.Write(LogLevel.Diagnostic,
        //                              i + ". Me.PassiveAuras - Name: " + aura.Value.Name + " - SpellId: " +
        //                              aura.Value.SpellId);
        //                i = i + 1;
        //            }
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");

        //            _lastGetAllMyAuras = DateTime.Now;
        //        }
        //    }
        //}

        #endregion

        #region GetUnitNear

        //private static WoWUnit _unitNear;

        //private static bool GetUnitNear()
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        _unitNear = null;
        //        _unitNear = (from unit in NearbyUnFriendlyUnits
        //                     where unit.IsValid
        //                     orderby unit.Distance ascending
        //                     where Me.Combat
        //                     where Me.CurrentMap.IsDungeon || Me.CurrentMap.IsRaid
        //                     where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
        //                            unit.IsTargetingMeOrPet)
        //                     select unit).FirstOrDefault();
        //        return _unitNear != null;
        //    }
        //}

        #endregion

        #region GetBestTarget

        private static WoWUnit UnitBestTarget;

        private static bool GetBestTarget()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                UnitBestTarget = null;
                if (Me.CurrentMap.IsBattleground || Me.CurrentMap.IsArena)
                {
                    UnitBestTarget = (from unit in NearbyUnFriendlyPlayers
                                      where unit.IsValid
                                      //orderby unit.ThreatInfo.RawPercent ascending
                                      orderby unit.CurrentHealth ascending
                                      //where Me.Combat
                                      where Attackable(unit, 40)
                                      select unit).FirstOrDefault();
                }

                if (UnitBestTarget == null && !Me.CurrentMap.IsBattleground && !Me.CurrentMap.IsArena)
                {
                    UnitBestTarget = (from unit in NearbyUnFriendlyUnits
                                      where unit.IsValid
                                      //orderby unit.ThreatInfo.RawPercent ascending
                                      orderby unit.CurrentHealth descending
                                      //where Me.Combat
                                      where !unit.IsSafelyBehind(Me)
                                      where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                                             unit.IsTargetingMeOrPet)
                                      where Attackable(unit, 40)
                                      select unit).FirstOrDefault();
                }
                return UnitBestTarget != null;
            }
        }

        #endregion

        #region GetBestFocus

        private static WoWUnit UnitBestFocus;

        private static bool GetBestFocus()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                UnitBestFocus = null;
                UnitBestFocus = (from unit in NearbyUnFriendlyPlayers
                                 where unit.IsValid
                                 where Me.CurrentTarget != null
                                 where unit != Me.CurrentTarget
                                 //orderby unit.ThreatInfo.RawPercent ascending
                                 where AttackableNoLoS(unit, 40)
                                 orderby TalentSort(unit) descending
                                 //orderby unit.CurrentHealth descending
                                 //where Me.Combat
                                 select unit).FirstOrDefault();

                //if (UnitBestFocus == null)
                //{
                //    UnitBestFocus = (from unit in NearbyUnFriendlyUnits
                //                     where unit.IsValid
                //                     where Me.CurrentTarget != null && unit != Me.CurrentTarget
                //                     //orderby unit.ThreatInfo.RawPercent ascending
                //                     orderby TalentSort(unit) descending
                //                     orderby unit.CurrentHealth descending
                //                     //where Me.Combat
                //                     where AttackableNoLoS(unit, 40)
                //                     select unit).FirstOrDefault();
                //}
                return UnitBestFocus != null;
            }
        }

        #endregion

        #region GetUnitHealerAround

        private static WoWUnit UnitHealerAround;

        private static bool GetUnitHealerAround()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                UnitHealerAround = null;
                UnitHealerAround = (from unit in NearbyUnFriendlyUnits
                                    where unit.Distance < 50
                                    where unit.IsPlayer
                                    where TalentSort(unit) == 4
                                    select unit).FirstOrDefault();

                return UnitHealerAround != null;
            }
        }

        #endregion

        #region IndexToKeys

        //private static Keys KeyTwo;

        private static Keys IndexToKeys(int index)
        {
            switch (index)
            {
                case 1:
                    return Keys.A;
                case 2:
                    return Keys.B;
                case 3:
                    return Keys.C;
                case 4:
                    return Keys.D;
                case 5:
                    return Keys.E;
                case 6:
                    return Keys.F;
                case 7:
                    return Keys.G;
                case 8:
                    return Keys.H;
                case 9:
                    return Keys.I;
                case 10:
                    return Keys.J;
                case 11:
                    return Keys.K;
                case 12:
                    return Keys.L;
                case 13:
                    return Keys.M;
                case 14:
                    return Keys.N;
                case 15:
                    return Keys.O;
                case 16:
                    return Keys.P;
                case 17:
                    return Keys.Q;
                case 18:
                    return Keys.R;
                case 19:
                    return Keys.S;
                case 20:
                    return Keys.T;
                case 21:
                    return Keys.U;
                case 22:
                    return Keys.V;
                case 23:
                    return Keys.W;
                case 24:
                    return Keys.X;
                case 25:
                    return Keys.Y;
                case 26:
                    return Keys.Z;
                case 27:
                    return Keys.D1;
                case 28:
                    return Keys.D2;
                case 29:
                    return Keys.D3;
                case 30:
                    return Keys.D4;
                case 31:
                    return Keys.D5;
                case 32:
                    return Keys.D6;
                case 33:
                    return Keys.D7;
                case 34:
                    return Keys.D8;
                case 35:
                    return Keys.D9;
                case 36:
                    return Keys.D0;
                case 37:
                    return Keys.Up;
                case 38:
                    return Keys.Down;
                case 39:
                    return Keys.Left;
                case 40:
                    return Keys.Right;
            }
            return Keys.None;
        }

        #endregion

        #region IsAttacking

        //private static bool IsAttacking()
        //{
        //    return Me.IsCasting && Me.CastingSpell.Name == "Denounce";
        //}

        #endregion

        #region IsDummy

        private static bool IsDummy(WoWUnit target)
        {
            if (target == null || !target.IsValid)
            {
                return false;
            }
            return target.Entry == 46647 || //Training Dummy Stormwind
                   target.Entry == 31144 || //Training Dummy Stormwind
                   target.Entry == 67127 || //Training Dummy Shine
                   target.Entry == 32666 || //Training Dummy
                   target.Entry == 32667 || //Training Dummy
                   target.Entry == 32546 || //Training Dummy
                   target.Entry == 31146; //Raider's Training Dummy
        }

        #endregion

        #region IsEnemy

        //public WoWUnit MyPartyorRaidUnit;

        private static bool IsMyPartyRaidMember(WoWUnit u)
        {
            if (u == null || !u.IsValid)
            {
                return false;
            }

            if (!u.IsPlayer)
            {
                if (Me.PartyMembers.Contains(u.CreatedByUnit) || Me.RaidMembers.Contains(u.CreatedByUnit))
                {
                    return true;
                }
            }
            else
            {
                if (Me.PartyMembers.Contains(u) || Me.RaidMembers.Contains(u))
                {
                    return true;
                }
            }

            return false;
        }

        private static bool IsEnemy(WoWUnit target)
        {
            if (target == null)
            {
                return false;
            }

            if (target.HasAura("Reshape Life") || //Reshape Life
                target.HasAura("Convert")) //Convert
            {
                return true;
            }

            if (!target.IsFriendly || IsDummy(target) && Me.Combat && Me.IsFacing(target))
            {
                return true;
            }
            return false;
        }

        #endregion

        #region IsMeorFocus

        //private static bool IsMeorFocus(WoWUnit target)
        //{
        //    if (target == Me ||
        //        target == Me.FocusedUnit && ValidUnit(Me.FocusedUnit) && !IsEnemy(Me.FocusedUnit) ||
        //        target == Me.CurrentTarget && ValidUnit(Me.CurrentTarget) && !IsEnemy(Me.CurrentTarget) ||
        //        Me.CurrentMap.IsArena)
        //    {
        //        return true;
        //    }
        //    return false;
        //}

        #endregion

        #region IsUnitsInLosOfEachOther

        //private static bool IsUnitsInLosOfEachOtherAtFeet(WoWUnit unitSource, WoWUnit unitDestination)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return (GameWorld.IsInLineOfSpellSight(
        //            unitSource.Location,
        //            unitDestination.Location));
        //    }
        //}

        //private static bool IsUnitsInLosOfEachOtherAtWaist(WoWUnit unitSource, WoWUnit unitDestination)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return (GameWorld.IsInLineOfSpellSight(
        //            unitSource.Location.Add(0.0f, 0.0f, unitSource.BoundingHeight/2),
        //            unitDestination.Location.Add(0.0f, 0.0f, unitDestination.BoundingHeight/2)));
        //    }
        //}

        //private static bool IsUnitsInLosOfEachOtherAtChest(WoWUnit unitSource, WoWUnit unitDestination)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return (GameWorld.IsInLineOfSpellSight(
        //            unitSource.Location.Add(0.0f, 0.0f, unitSource.BoundingHeight*0.75f),
        //            unitDestination.Location.Add(0.0f, 0.0f, unitDestination.BoundingHeight*0.75f)));
        //    }
        //}

        //private static bool IsUnitsInLosOfEachOtherAtHead(WoWUnit unitSource, WoWUnit unitDestination)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return (GameWorld.IsInLineOfSpellSight(
        //            unitSource.Location.Add(0.0f, 0.0f, unitSource.BoundingHeight),
        //            unitDestination.Location.Add(0.0f, 0.0f, unitDestination.BoundingHeight)));
        //    }
        //}

        #endregion

        #region MeIsTank

        private static bool MeIsTank
        {
            get
            {
                //using (StyxWoW.Memory.AcquireFrame())
                {
                    //return (StyxWoW.Me.Role & WoWPartyMember.GroupRole.Tank) != 0 ||
                    //        Tanks.All(t => !t.IsAlive) && StyxWoW.Me.HasAura("Bear Form");
                    return (StyxWoW.Me.Role & WoWPartyMember.GroupRole.Tank) != 0;
                }
            }
        }

        #endregion

        #region MyAura

        private static bool MyAura(string auraName, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return false;

                bool aura = u.GetAllAuras().Any(a => a.Name == auraName && a.CreatorGuid == Me.Guid);

                return aura;
                //return u.ActiveAuras.Any(a => a.Value.Name == auraName && a.Value.CreatorGuid == Me.Guid);
            }
        }


        private static bool MyAura(int auraID, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return false;

                bool aura = u.GetAllAuras().Any(a => a.SpellId == auraID && a.CreatorGuid == Me.Guid);

                return aura;

                //return u.ActiveAuras.Any(a => a.Value.SpellId == auraID && a.Value.CreatorGuid == Me.Guid);
            }
        }

        #endregion

        #region MyAuraTimeLeft

        private static double MyAuraTimeLeft(string auraName, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        //private static double MyAuraTimeLeft(int auraID, WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == Me.Guid);

        //        if (aura == null)
        //        {
        //            return 0;
        //        }
        //        return aura.TimeLeft.TotalMilliseconds;
        //    }
        //}

        #endregion

        #region LogTest

        //private static Composite LogTest(string message)
        //{
        //    return new Action(delegate
        //                          {
        //                              Logging.Write(LogLevel.Diagnostic, "LogTest: " + message);
        //                              return RunStatus.Failure;
        //                          });
        //}

        #endregion

        #region UnitAuraTimeLeft

        //private static double UnitAuraTimeLeft(string auraName, WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == u.Guid);

        //        if (aura == null)
        //        {
        //            return 0;
        //        }
        //        return aura.TimeLeft.TotalMilliseconds;
        //    }
        //}

        //private static double UnitAuraTimeLeft(int auraID, WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null)
        //            return 0;

        //        WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == u.Guid);

        //        if (aura == null)
        //        {
        //            return 0;
        //        }
        //        return aura.TimeLeft.TotalMilliseconds;
        //    }
        //}

        #endregion

        #region MyAuraStackCount

        //private static double MyAuraStackCount(string auraName, WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == u.Guid);

        //        if (aura == null)
        //        {
        //            return 0;
        //        }
        //        return aura.StackCount;
        //    }
        //}

        //private static double MyAuraStackCount(int auraID, WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == u.Guid);

        //        if (aura == null)
        //        {
        //            return 0;
        //        }
        //        return aura.StackCount;
        //    }
        //}

        #endregion

        #region SafelyFacingTarget

        private static void SafelyFacingTarget(WoWUnit unit)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                //if (THSettings.Instance.AutoFace && !IsOverrideModeOn && unit != null && !Me.IsFacing(unit))
                //{
                //    unit.Face();
                //}

                //if (unit == null ||
                //    SpecialUnit.Contains(unit.Entry) ||
                //    Blacklist.Contains(unit.Guid, BlacklistFlags.All))
                //{
                //    return;
                //}

                if (unit == null)
                {
                    return;
                }

                if (!unit.IsValid)
                {
                    return;
                }

                if (THSettings.Instance.AutoFace && !IsOverrideModeOn && !Me.IsSafelyFacing(unit))
                {
                    unit.Face();
                }
            }
        }

        #endregion

        #region SafeName

        private static string SafeName(WoWUnit unit)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (unit == null || !unit.IsValid)
                {
                    return "null or invalid";
                }
                if (unit == Me)
                {
                    return "Myself";
                }
                if (unit.IsPlayer)
                {
                    return unit.Class.ToString();
                }
                if (unit.IsPet)
                {
                    return unit.CreatureType.ToString();
                }
            }
            return unit.Name;
        }

        #endregion

        #region SetAutoAttack

        private static Composite SetAutoAttack()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                return new Action(delegate
                    {
                        if (Me.IsAutoAttacking &&
                            (!THSettings.Instance.AutoAttack ||
                             !Attackable(Me.CurrentTarget, 40) ||
                             Me.CurrentTarget.HasAura("Water Shield") &&
                             Me.CurrentMap.IsArena))
                        {
                            //Logging.Write("Stop Attack");
                            Lua.DoString("RunMacroText('/stopattack');");
                        }

                        //Disable this, it conflic with the targeting system
                        if (THSettings.Instance.AutoAttack &&
                            !Me.Mounted &&
                            !Me.IsAutoAttacking &&
                            !Me.HasAura("Camouflage") &&
                            Attackable(Me.CurrentTarget, 50))
                        {
                            //Logging.Write("Start Attack");
                            Lua.DoString("RunMacroText('/startattack');");
                        }
                        return RunStatus.Failure;
                    });
            }
        }

        #endregion

        #region TalentSort

        private static byte TalentSort(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null)
                {
                    return 0;
                }

                if (!target.IsPlayer)
                {
                    return 0;
                }

                if (target.Class == WoWClass.DeathKnight)
                {
                    return 1;
                }

                if (target.Class == WoWClass.Druid)
                {
                    if (target.Buffs.ContainsKey("Moonkin Form"))
                        return 3;
                    if ((target.Buffs.ContainsKey("Leader of the Pack") &&
                         target.Buffs["Leader of the Pack"].CreatorGuid == target.Guid) ||
                        target.MaxMana < target.MaxHealth/2)
                        return 1;
                    return 4;
                }

                if (target.Class == WoWClass.Hunter)
                {
                    return 2;
                }

                if (target.Class == WoWClass.Mage)
                {
                    return 3;
                }

                if (target.Class == WoWClass.Monk)
                {
                    if (target.MaxMana >= target.MaxHealth/2)
                        return 4;
                    return 1;
                }

                if (target.Class == WoWClass.Paladin)
                {
                    if (target.MaxMana > target.MaxHealth/2)
                        return 4;
                    return 1;
                }

                if (target.Class == WoWClass.Priest)
                {
                    if (target.HasAura("Shadowform"))
                        return 3;
                    return 4;
                }

                if (target.Class == WoWClass.Rogue)
                {
                    return 1;
                }

                if (target.Class == WoWClass.Shaman)
                {
                    if (target.MaxMana < target.MaxHealth/2)
                        return 1;
                    if (target.Buffs.ContainsKey("Elemental Oath") &&
                        target.Buffs["Elemental Oath"].CreatorGuid == target.Guid)
                        return 3;
                    return 4;
                }

                if (target.Class == WoWClass.Warlock)
                {
                    return 3;
                }

                if (target.Class == WoWClass.Warrior)
                {
                    return 1;
                }

                return 0;
            }
        }

        //private static byte TalentSortSimple(WoWUnit target)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        byte sortSimple = TalentSort(target);

        //        if (sortSimple == 4)
        //        {
        //            return 4;
        //        }

        //        if (sortSimple < 4 && sortSimple > 0)
        //        {
        //            return 1;
        //        }

        //        return 0;
        //    }
        //}

        #endregion

        #region TalentValue

        private static int TalentValue(int blood, int frost, int unholy)
        {
            return GetCurrentSpec() == "Blood" ? blood : (GetCurrentSpec() == "Unholy" ? unholy : frost);
        }

        private static bool TalentValue(bool blood, bool frost, bool unholy)
        {
            return GetCurrentSpec() == "Blood" ? blood : (GetCurrentSpec() == "Unholy" ? unholy : frost);
        }

        #endregion

        #region UpdateStatusEvent

        private static void UpdateStatusEvent(object sender, LuaEventArgs args)
        {
            THSettings.Instance.UpdateStatus = true;
        }

        #endregion

        #region OnBotStartedEvent

        private static void OnBotStartedEvent(object o)
        {
            if (Me.Inventory.Equipped.Hands != null &&
                Me.Inventory.Equipped.Hands.Name.Contains("Malevolent Gladiator's Scaled Gauntlets"))
            {
            }
            Logging.Write("----------------------------------");
            Logging.Write("Update Status on Bot Start");
            Logging.Write("----------------------------------");

            THSettings.Instance.Pause = false;
            THSettings.Instance.UpdateStatus = true;
        }

        #endregion

        #region SpecialUnit

        private static readonly HashSet<uint> SpecialUnit = new HashSet<uint>
            {
                60491, //Sha of Anger
                62346, //Galleon
                60410, //Elegon
                60776, //Empyreal Focus
                60793, //Celestial Protector
                60913, //Energy Charge
                60143, //garajal-the-spiritbinder
                60412, //Empyreal Focus
                63667, //garalon
            };

        #endregion

        #region UpdateCurrentMap

        //public string CurrentMap;

        //private static void UpdateCurrentMapEvent(BotEvents.Player.MapChangedEventArgs args)
        //{
        //    THSettings.Instance.UpdateStatus = true;
        //}

        //private static void UpdateCurrentMap()
        //{
        //    if (Me.CurrentMap.IsArena)
        //    {
        //        CurrentMap = "Arena";
        //    }
        //    else if (Me.CurrentMap.IsBattleground && Me.IsFFAPvPFlagged)
        //    {
        //        CurrentMap = "Rated Battleground";
        //    }
        //    else if (Me.CurrentMap.IsBattleground)
        //    {
        //        CurrentMap = "Battleground";
        //    }
        //    else if (Me.CurrentMap.IsDungeon)
        //    {
        //        CurrentMap = "Dungeon";
        //    }
        //    else if (Me.CurrentMap.IsRaid)
        //    {
        //        CurrentMap = "Raid";
        //    }
        //    else
        //    {
        //        CurrentMap = "World";
        //    }

        //    Logging.Write("----------------------------------");
        //    Logging.Write("CurrentMap: " + CurrentMap);
        //    Logging.Write("----------------------------------");
        //}

        #endregion

        #region UpdateEventHandler

        private static void UpdateEventHandler()
        {
            Logging.Write(LogLevel.Diagnostic, "UpdateEventHandler");

            if (EventHandlers.CombatLogAttached &&
                (TreeRoot.Current.Name == "Tyrael" ||
                 TreeRoot.Current.Name == "LazyRaider" ||
                 TreeRoot.Current.Name == "Raid Bot" ||
                 TreeRoot.Current.Name == "Combat Bot"))
            {
                EventHandlers.DetachCombatLogEvent();
                Logging.Write(LogLevel.Diagnostic, "DetachCombatLogEvent");
            }

            if (!EventHandlers.CombatLogAttached &&
                TreeRoot.Current.Name != "Tyrael" &&
                TreeRoot.Current.Name != "LazyRaider" &&
                TreeRoot.Current.Name != "Raid Bot" &&
                TreeRoot.Current.Name != "Combat Bot")
            {
                EventHandlers.AttachCombatLogEvent();
                Logging.Write(LogLevel.Diagnostic, "AttachCombatLogEvent");
            }
        }

        #endregion

        #region UpdateMyLatency

        private static double _myLatency;

        private static void UpdateMyLatency()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (THSettings.Instance.LagTolerance)
                {
                    //If SLagTolerance enabled, start casting next spell MyLatency Millisecond before GlobalCooldown ready.

                    _myLatency = (StyxWoW.WoWClient.Latency);

                    //Use here because Lag Tolerance cap at 400
                    //Logging.Write("----------------------------------");
                    //Logging.Write("MyLatency: " + MyLatency);
                    //Logging.Write("----------------------------------");

                    if (_myLatency > 400)
                    {
                        //Lag Tolerance cap at 400
                        _myLatency = 400;
                    }
                }
                else
                {
                    _myLatency = 0;
                }
            }
        }

        #endregion

        #region UpdateMyTalent

        private static string _hasTalent = "";

        private static void UpdateMyTalentEvent(object sender, LuaEventArgs args)
        {
            UpdateMyTalent();
        }

        private static void UpdateMyTalent()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                _hasTalent = "";
                for (int i = 1; i <= 18; i++)
                {
                    _hasTalent = _hasTalent +
                                 Lua.GetReturnVal<String>(
                                     string.Format(
                                         "local t= select(5,GetTalentInfo({0})) if t == true then return '['..select(1,GetTalentInfo({0}))..'] ' end return nil",
                                         i), 0);
                }

                Logging.Write("----------------------------------");
                Logging.Write("Talent:");
                Logging.Write(_hasTalent);
                Logging.Write("----------------------------------");
                _hasTalent = "";
            }
        }

        #endregion

        #region UseHealthstone

        private static Composite UseHealthstone()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                return
                    new Decorator(
                        ret =>
                        THSettings.Instance.HealthStone &&
                        Me.Combat &&
                        Me.HealthPercent < THSettings.Instance.HealthStoneHP &&
                        Me.CurrentTarget != null &&
                        Me.CurrentTarget.CurrentHealth > Me.HealthPercent,
                        new Action(delegate
                            {
                                WoWItem hs = Me.BagItems.FirstOrDefault(o => o.Entry == 5512);
                                //5512 Healthstone
                                if (hs != null && hs.CooldownTimeLeft.TotalMilliseconds <= _myLatency)
                                {
                                    hs.Use();
                                    //Lua.DoString("RunMacroText(\"/s Used Healthstone\")");
                                    Logging.Write("Use Healthstone at " + Math.Round(Me.HealthPercent, 0) + "%");
                                }
                                return RunStatus.Failure;
                            })
                        );
            }
        }

        #endregion

        #region UpdateMyGlyph

        private static void UpdateMyGlyphEvent(object sender, LuaEventArgs args)
        {
            UpdateMyGlyph();
        }

        //private static readonly HashSet<string> NoGCDSpells = new HashSet<string> { };
        private static string HasGlyph;
        private static string HasGlyphName;

        private static void UpdateMyGlyph()
        {
            HasGlyph = "";
            HasGlyphName = "";
            //using (StyxWoW.Memory.AcquireFrame())
            {
                var glyphCount = Lua.GetReturnVal<int>("return GetNumGlyphSockets()", 0);

                if (glyphCount != 0)
                {
                    for (int i = 1; i <= glyphCount; i++)
                    {
                        string lua =
                            String.Format(
                                "local enabled, glyphType, glyphTooltipIndex, glyphSpellID, icon = GetGlyphSocketInfo({0});if (enabled) then return glyphSpellID else return 0 end",
                                i);

                        var glyphSpellId = Lua.GetReturnVal<int>(lua, 0);

                        try
                        {
                            if (glyphSpellId > 0)
                            {
                                HasGlyphName = HasGlyphName + "[" + (WoWSpell.FromId(glyphSpellId)) + " - " +
                                               glyphSpellId +
                                               "] ";
                                HasGlyph = HasGlyph + "[" + glyphSpellId + "] ";
                            }
                            else
                            {
                                Logging.Write("Glyphdetection - No Glyph in slot " + i);
                                //TreeRoot.Stop();
                            }
                        }
                        catch (Exception ex)
                        {
                            Logging.Write("We couldn't detect your Glyphs");
                            Logging.Write("Report this message to us: " + ex);
                            //TreeRoot.Stop();
                        }
                    }
                }

                Logging.Write("----------------------------------");
                Logging.Write("Glyph:");
                Logging.Write(HasGlyphName);
                Logging.Write("----------------------------------");
            }
        }

        #endregion

        #region UpdateStatus

        private static string UseRotation;

        private static void UpdateStatus()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (THSettings.Instance.UpdateStatus)
                    if (Me.IsValid)
                    {
                        {
                            DoNotFreezingTrap = DateTime.Now;
                            //Reset BurstLast on start
                            BurstLast = DateTime.Now;

                            //if (THSettings.Instance.LastSavedSpec != GetCurrentSpec())
                            //{
                            //    Logging.Write("----------------------------------");
                            //    Logging.Write("You just change specialization to " + GetCurrentSpec() + ". ");
                            //    Logging.Write("Please select the appropriate settings");
                            //    Logging.Write("----------------------------------");

                            //    OnButtonPress();
                            //}

                            Logging.Write("----------------------------------");
                            Logging.Write("Building Rotation base on current Talents and Glyphs......");
                            Logging.Write("----------------------------------");
                            Logging.Write("");

                            //if (TreeRoot.Current.Name != "Questing" && 
                            //    TreeRoot.Current.Name != "Grind Bot" &&
                            //    TreeRoot.Current.Name != "LazyRaider" && 
                            //    TreeRoot.Current.Name != "BGBuddy" &&
                            //    TreeRoot.Current.Name != "DungeonBuddy" && 
                            //    TreeRoot.Current.Name != "Mixed Mode" && 
                            //    GetAsyncKeyState(Keys.F10) == 0)
                            //{
                            //    Logging.Write("This CC only work with DungeonBuddy - LazyRaider - Questing - Grind Bot.");
                            //    Logging.Write("Custom Class Stop.");

                            //    TreeRoot.Stop();
                            //}

                            if (TreeRoot.Current.Name == "LazyRaider" && !THSettings.Instance.AutoMove)
                            {
                                THSettings.Instance.AutoMove = false;
                                //Logging.Write(LogLevel.Diagnostic,
                                //              "EnableMovement: " + THSettings.Instance.EnableMovement);
                            }
                            //else
                            //{
                            //    THSettings.Instance.SAutoMove = true;
                            //    THSettings.Instance.SAutoTarget = true;
                            //Logging.Write(LogLevel.Diagnostic,
                            //              "EnableMovement: " + THSettings.Instance.EnableMovement);
                            //}

                            //if (Me.Level < 85)
                            //{
                            //    Logging.Write("This CC only work on Level 85-90.");
                            //    //TreeRoot.Stop();
                            //    return;
                            //}
                            UpdateEventHandler();

                            UpdateMyTalent();

                            UpdateMyGlyph();

                            UpdateMyLatency();

                            PetSpellsUpdate();

                            PetAutocastOff();

                            Logging.Write("----------------------------------");
                            Logging.Write("Building Rotation Completed");
                            Logging.Write("----------------------------------");
                            Logging.Write("");

                            Logging.Write("----------------------------------");
                            Logging.Write("Press Control + " + IndexToKeys(THSettings.Instance.PauseKey) +
                                          " To Toggle Pause Mode.");
                            Logging.Write("----------------------------------");
                            Logging.Write("");

                            //Logging.Write("----------------------------------");
                            //Logging.Write("Press Control + " + IndexToKeys(THSettings.Instance.AoEKey) +
                            //              " To Toggle Pause Mode.");
                            //Logging.Write("----------------------------------");
                            //Logging.Write("");

                            if (THSettings.Instance.BurstKey > 6)
                            {
                                Logging.Write("----------------------------------");
                                Logging.Write("Press Control + " + IndexToKeys(THSettings.Instance.BurstKey - 6) +
                                              " To Toggle Burst Mode");
                                Logging.Write("----------------------------------");
                                Logging.Write("");
                            }
                            THSettings.Instance.UpdateStatus = false;

                            //CheckEnvironmentLast = DateTime.Now;

                            switch (Me.Specialization)
                            {
                                case WoWSpec.HunterBeastMastery:
                                    UseRotation = "HunterBeastMastery";
                                    break;
                                case WoWSpec.HunterMarksmanship:
                                    UseRotation = "HunterMarksmanship";
                                    break;
                                case WoWSpec.HunterSurvival:
                                    UseRotation = "HunterSurvival";
                                    break;
                                default:
                                    UseRotation = "HunterBeastMastery";
                                    break;
                            }
                        }
                    }
            }
        }

        #endregion

        #region ValidUnit

        private static bool ValidUnit(WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u != null &&
                    u.IsValid &&
                    u.Attackable &&
                    u.IsAlive &&
                    !Blacklist.Contains(u.Guid, BlacklistFlags.All))
                {
                    return true;
                }

                return false;
                //if (u == null || !u.IsValid || Blacklist.Contains(u.Guid, BlacklistFlags.All) || !u.Attackable ||
                //    !u.IsAlive || !u.CanSelect || u.IsDead ||
                //    u.IsCritter && (u.CurrentTarget == null || u.CurrentTarget != null && u.CurrentTarget != Me) ||
                //    u.IsNonCombatPet)
                //{
                //    return false;
                //}
                //return true;
            }
        }

        #endregion
    }
}